﻿using DAL;
using DAL.Entities;
using DAL.JSGN;
using DAL.RYGL;
using DAL.Unit;
using DAL.YQZS;
using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BLL.RYGL
{
    public class EmployeeBLL
    {
        private readonly DataContext _dataContext;
        private readonly EmployeeDAL _employeeDAL;
        private readonly YqzsDAL _yqzsDAL;
        private readonly TrackDAL _trackDAL;
        private readonly AttachmentDAL _attachmentDAL;
        private readonly LoginUserDal _loginUserDal;
        private readonly InOutDAL _inoutDAL;
        private readonly UnitDAL _unitDAL;

        public EmployeeBLL()
        {
            _dataContext = new DataContext();
            _employeeDAL = new EmployeeDAL(_dataContext);
            _inoutDAL = new InOutDAL(_dataContext);
            _yqzsDAL = new YqzsDAL(_dataContext);
            _trackDAL = new TrackDAL(_dataContext);
            _attachmentDAL = new AttachmentDAL(_dataContext);
            _loginUserDal = new LoginUserDal();
            _unitDAL = new UnitDAL();
        }

        public Task<IEnumerable<EmployeeModel>> ListAsync(string deptid, string name, string employeeType, string inoutType, int pageSize, int pageIndex, out int total)
        {
            var data = _employeeDAL.ListAsync(deptid, name, employeeType, inoutType, pageSize, pageIndex, out total).Result;
            var models = data.Select(x => new EmployeeModel()
            {
                EmployeeId = x.EmployeeId,
                DepartmentId = x.DepartmentId,
                DepartmentName = x.DepartmentName,
                DisplayName = x.DisplayName,
                EmployeeNumber = x.EmployeeNumber,
                EmployeeType = x.EmployeeType,
                Gender = x.Gender,
                Hometown = x.Hometown,
                IdentityNumber = x.IdentityNumber,
                PhoneNumber = x.PhoneNumber,
                Post = x.Post,
                Age = x.Age,
                ReworkDate = x.ReworkDate,
                CreateTime = x.CreateTime,
            });
            return Task.FromResult(models);
        }

        public async Task<EmployeeModel> GetAsync(Guid id)
        {
            var entity = await _employeeDAL.GetAsync(id);
            var inoutEntity = await _inoutDAL.GetAsync(id);
            var yqzsEntity = await _yqzsDAL.GetAsync(inoutEntity?.InOutId ?? Guid.Empty);
            var trackEntities = await _trackDAL.ListAsync(yqzsEntity?.YqzsId ?? Guid.Empty);
            var attachmentEntity = (await _attachmentDAL.ListAsync(id, "photo")).FirstOrDefault();
            var attachmentEntities = await _attachmentDAL.ListAsync(yqzsEntity?.YqzsId ?? Guid.Empty, "yqzs");
            if (entity == null) return null;
            if (string.IsNullOrEmpty(entity.EmployeeStatus)) yqzsEntity = null;
            return new EmployeeModel()
            {
                EmployeeId = entity.EmployeeId,
                DepartmentId = entity.DepartmentId,
                DepartmentName = entity.DepartmentName,
                DisplayName = entity.DisplayName,
                EmployeeNumber = entity.EmployeeNumber,
                EmployeeType = entity.EmployeeType,
                Gender = entity.Gender,
                Hometown = entity.Hometown,
                IdentityNumber = entity.IdentityNumber,
                PhoneNumber = entity.PhoneNumber,
                Post = entity.Post,
                Age = entity.Age,
                ReworkDate = entity.ReworkDate,
                CreateTime = entity.CreateTime,
                EmployeeStatus = entity.EmployeeStatus,
                EmployeeImage = attachmentEntity == null ? null : new AttachmentModel() { AttachmentId = attachmentEntity.AttachmentId, Extension = attachmentEntity.Extension, FileName = attachmentEntity.FileName, MediaType = attachmentEntity.MediaType },
                Yqzs = yqzsEntity == null ? null : new YqzsModel()
                {
                    YqzsId = yqzsEntity.YqzsId,
                    BodyTemperature = yqzsEntity.BodyTemperature,
                    HasTouched = yqzsEntity.HasTouched,
                    Remark = yqzsEntity.Remark,
                    StayWorking = yqzsEntity.StayWorking,
                    SurveyResult = yqzsEntity.SurveyResult,
                    Symptom = yqzsEntity.Symptom,
                    Tracks = trackEntities.Select(y => new TrackModel() { TrackId = y.TrackId, ArrivingPlace = y.ArrivingPlace, ArrivingTime = y.ArrivingTime, DeparturePlace = y.DeparturePlace, DepartureTime = y.DepartureTime, TrackCode = y.TrackCode, Trasportation = y.Trasportation }),
                    Attachments = attachmentEntities.Select(x => new AttachmentModel() { AttachmentId = x.AttachmentId, Extension = x.Extension, FileName = x.FileName, MediaType = x.MediaType }).ToList()
                }
            };
        }

        public async Task CreateAsync(EmployeeModel model)
        {
            if (await _employeeDAL.Exists(model.DepartmentId, model.IdentityNumber)) throw new EmployeeDuplicateException();

            var entity = new Employee()
            {
                EmployeeId = model.EmployeeId,
                DepartmentId = model.DepartmentId,
                DepartmentName = model.DepartmentName,
                DisplayName = model.DisplayName,
                EmployeeNumber = model.EmployeeNumber,
                EmployeeType = model.EmployeeType,
                Gender = model.Gender,
                Hometown = model.Hometown,
                IdentityNumber = model.IdentityNumber,
                PhoneNumber = model.PhoneNumber,
                Post = model.Post,
                ReworkDate = model.ReworkDate,
                Age = model.Age,
                CreateTime = model.CreateTime,
                EmployeeStatus = model.EmployeeStatus
            };
            var inoutEntity = new InOut()
            {
                InOutId = Guid.NewGuid(),
                CreateTime = DateTime.Now,
                InOutType = model.EmployeeStatus == "已进场" ? "进场" : "退场"
            };
            entity.InOuts = new List<InOut>() { inoutEntity };
            if (model.Yqzs != null)
            {
                inoutEntity.Yqzs = new Yqzs()
                {
                    YqzsId = inoutEntity.InOutId,
                    BodyTemperature = model.Yqzs.BodyTemperature,
                    HasTouched = model.Yqzs.HasTouched,
                    Remark = model.Yqzs.Remark,
                    StayWorking = model.Yqzs.StayWorking,
                    SurveyResult = model.Yqzs.SurveyResult,
                    Symptom = model.Yqzs.Symptom,
                    Tracks = model.Yqzs.Tracks == null ? null : model.Yqzs.Tracks.Select(y => new Track() { TrackId = y.TrackId, ArrivingPlace = y.ArrivingPlace, ArrivingTime = y.ArrivingTime, DeparturePlace = y.DeparturePlace, DepartureTime = y.DepartureTime, TrackCode = y.TrackCode, Trasportation = y.Trasportation }).ToList()
                };
            }
            await _employeeDAL.CreateAsync(entity);

            var attachmentEntities = new List<Attachment>();
            if (model.EmployeeImage != null)
            {
                attachmentEntities.Add(new Attachment()
                {
                    AttachmentId = model.EmployeeImage.AttachmentId,
                    FileName = model.EmployeeImage.FileName,
                    FileStream = model.EmployeeImage.FileStream,
                    Extension = model.EmployeeImage.Extension,
                    MediaType = model.EmployeeImage.MediaType,
                    Option = "photo",
                    BusinessId = model.EmployeeId.ToString()
                });
            }
            if (model.Yqzs != null && model.Yqzs.Attachments != null)
            {
                foreach (var item in model.Yqzs.Attachments)
                {
                    attachmentEntities.Add(new Attachment()
                    {
                        AttachmentId = item.AttachmentId,
                        FileName = item.FileName,
                        FileStream = item.FileStream,
                        Extension = item.Extension,
                        MediaType = item.MediaType,
                        Option = "yqzs",
                        BusinessId = inoutEntity.InOutId.ToString()
                    });
                }
            }
            await _attachmentDAL.CreateAsync(attachmentEntities);

            await _employeeDAL.SaveChangesAsync();

            var userEntity = _loginUserDal.GetSingleDataByUserId(model.UserId);
            if (!string.IsNullOrEmpty(userEntity.DepartId))
            {
                var dept = _unitDAL.GetEntity(userEntity.DepartId);
                if (dept == null)
                    _loginUserDal.UpdateUserInfo(model.UserId, model.DepartmentId, model.DepartmentName, model.EmployeeId.ToString(), model.EmployeeType == "管理人员" ? 1 : 0);
            }
            else
                _loginUserDal.UpdateUserInfo(model.UserId, model.DepartmentId, model.DepartmentName, model.EmployeeId.ToString(), model.EmployeeType == "管理人员" ? 1 : 0);

        }

        public async Task CreateAsync(IEnumerable<EmployeeModel> models, string deptid)
        {
            var dept = await _unitDAL.GetEntity(deptid);

            foreach (var item in models)
            {
                var model = item;
                var entity = new Employee()
                {
                    EmployeeId = model.EmployeeId,
                    DepartmentId = model.DepartmentId,
                    DepartmentName = dept?.UnitName,
                    DisplayName = model.DisplayName,
                    EmployeeNumber = model.EmployeeNumber,
                    EmployeeType = model.EmployeeType,
                    Gender = model.Gender,
                    Hometown = model.Hometown,
                    IdentityNumber = model.IdentityNumber,
                    PhoneNumber = model.PhoneNumber,
                    Post = model.Post,
                    ReworkDate = model.ReworkDate,
                    Age = model.Age,
                    CreateTime = model.CreateTime,
                    EmployeeStatus = model.EmployeeStatus,
                    InOuts = new List<InOut>()
                };
                var inoutEntity = new InOut()
                {
                    InOutId = Guid.NewGuid(),
                    CreateTime = DateTime.Now,
                    InOutType = model.EmployeeStatus == "已进场" ? "进场" : "退场"
                };
                inoutEntity.Yqzs = new Yqzs()
                {
                    YqzsId = inoutEntity.InOutId
                };
                entity.InOuts.Add(inoutEntity);

                _employeeDAL.CreateAsync(entity);
            }

            await _employeeDAL.SaveChangesAsync();
        }

        public async Task UpateAsync(EmployeeModel model)
        {
            if (await _employeeDAL.Exists(model.DepartmentId, model.IdentityNumber, model.EmployeeId)) throw new EmployeeDuplicateException();

            var entity = await _employeeDAL.GetAsync(model.EmployeeId);
            entity.DepartmentId = model.DepartmentId;
            entity.DepartmentName = model.DepartmentName;
            entity.DisplayName = model.DisplayName;
            entity.EmployeeNumber = model.EmployeeNumber;
            entity.EmployeeType = model.EmployeeType;
            entity.Gender = model.Gender;
            entity.Hometown = model.Hometown;
            entity.IdentityNumber = model.IdentityNumber;
            entity.PhoneNumber = model.PhoneNumber;
            entity.Post = model.Post;
            entity.Age = model.Age;
            entity.ReworkDate = model.ReworkDate;

            if (model.EmployeeStatus != entity.EmployeeStatus)
            {
                if (model.EmployeeStatus == "已进场")
                {
                    var inoutEntity = new InOut()
                    {
                        InOutId = Guid.NewGuid(),
                        InOutType = "进场",
                        CreateTime = DateTime.Now,
                        EmployeeId = entity.EmployeeId
                    };
                    await _inoutDAL.CreateAsync(inoutEntity);

                    if (model.Yqzs != null)
                    {
                        var yqzsEntity = new Yqzs()
                        {
                            YqzsId = inoutEntity.InOutId,
                            BodyTemperature = model.Yqzs.BodyTemperature,
                            HasTouched = model.Yqzs.HasTouched,
                            Remark = model.Yqzs.Remark,
                            StayWorking = model.Yqzs.StayWorking,
                            SurveyResult = model.Yqzs.SurveyResult,
                            Symptom = model.Yqzs.Symptom,
                            Tracks = model.Yqzs.Tracks == null ? null : model.Yqzs.Tracks.Select(y => new Track() { TrackId = y.TrackId, ArrivingPlace = y.ArrivingPlace, ArrivingTime = y.ArrivingTime, DeparturePlace = y.DeparturePlace, DepartureTime = y.DepartureTime, TrackCode = y.TrackCode, Trasportation = y.Trasportation }).ToList(),
                        };
                        _yqzsDAL.CreateAsync(yqzsEntity);

                        if (model.Yqzs.Attachments != null)
                        {
                            var attachmentEntities = model.Yqzs.Attachments.Select(x => new Attachment()
                            {
                                AttachmentId = x.AttachmentId,
                                FileName = x.FileName,
                                FileStream = x.FileStream,
                                Extension = x.Extension,
                                MediaType = x.MediaType,
                                Option = "yqzs",
                                BusinessId = yqzsEntity.YqzsId.ToString()
                            });
                            _attachmentDAL.CreateAsync(attachmentEntities);
                        }
                    }
                }
                else
                {
                    var inoutEntity = new InOut()
                    {
                        InOutId = Guid.NewGuid(),
                        InOutType = "退场",
                        CreateTime = DateTime.Now,
                        EmployeeId = entity.EmployeeId
                    };
                    await _inoutDAL.CreateAsync(inoutEntity);
                }
            }
            else
            {
                if (model.Yqzs != null)
                {
                    var yqzsEntity = await _yqzsDAL.GetAsync(model.Yqzs.YqzsId);
                    yqzsEntity.BodyTemperature = model.Yqzs.BodyTemperature;
                    yqzsEntity.HasTouched = model.Yqzs.HasTouched;
                    yqzsEntity.Remark = model.Yqzs.Remark;
                    yqzsEntity.StayWorking = model.Yqzs.StayWorking;
                    yqzsEntity.SurveyResult = model.Yqzs.SurveyResult;
                    yqzsEntity.Symptom = model.Yqzs.Symptom;
                    await _yqzsDAL.UpdateAsync(yqzsEntity);

                    if (model.Yqzs.Tracks != null)
                    {
                        var tracks = await _trackDAL.ListAsync(model.Yqzs.YqzsId);
                        foreach (var item in model.Yqzs.Tracks)
                        {
                            if (tracks.Any(x => x.TrackId == item.TrackId))
                            {
                                var trackEntity = tracks.First(x => x.TrackId == item.TrackId);
                                trackEntity.ArrivingPlace = item.ArrivingPlace;
                                trackEntity.ArrivingTime = item.ArrivingTime;
                                trackEntity.DeparturePlace = item.DeparturePlace;
                                trackEntity.DepartureTime = item.DepartureTime;
                                trackEntity.TrackCode = item.TrackCode;
                                trackEntity.Trasportation = item.Trasportation;
                                await _trackDAL.UpdateAsync(trackEntity);
                            }
                            else
                            {
                                await _trackDAL.CreateAsync(new Track()
                                {
                                    TrackId = item.TrackId,
                                    ArrivingPlace = item.ArrivingPlace,
                                    ArrivingTime = item.ArrivingTime,
                                    DeparturePlace = item.DeparturePlace,
                                    DepartureTime = item.DepartureTime,
                                    TrackCode = item.TrackCode,
                                    Trasportation = item.Trasportation,
                                    YqzsId = model.Yqzs.YqzsId
                                });
                            }
                        }
                        var deleteTrasks = tracks.Where(x => !model.Yqzs.Tracks.Any(y => y.TrackId == x.TrackId));
                        await _trackDAL.DeleteAsync(deleteTrasks);
                    }

                    if (model.Yqzs.Attachments != null)
                    {
                        var attachmentEntities = await _attachmentDAL.ListAsync(model.Yqzs.YqzsId, "yqzs");
                        foreach (var item in model.Yqzs.Attachments)
                        {
                            if (attachmentEntities.Any(x => x.AttachmentId == item.AttachmentId)) continue;

                            await _attachmentDAL.CreateAsync(new Attachment()
                            {
                                AttachmentId = item.AttachmentId,
                                FileName = item.FileName,
                                FileStream = item.FileStream,
                                Extension = item.Extension,
                                MediaType = item.MediaType,
                                Option = "yqzs",
                                BusinessId = model.Yqzs.YqzsId.ToString()
                            });
                        }
                        var deleteAttachments = attachmentEntities.Where(x => !model.Yqzs.Attachments.Any(y => y.AttachmentId == x.AttachmentId));
                        await _attachmentDAL.DeleteAsync(deleteAttachments);
                    }
                }
            }

            if (model.EmployeeImage != null)
            {
                var attachmentEntity = (await _attachmentDAL.ListAsync(model.EmployeeId, "photo")).FirstOrDefault();
                if (attachmentEntity == null)
                {
                    attachmentEntity = new Attachment()
                    {
                        AttachmentId = model.EmployeeImage.AttachmentId,
                        FileName = model.EmployeeImage.FileName,
                        FileStream = model.EmployeeImage.FileStream,
                        Extension = model.EmployeeImage.Extension,
                        MediaType = model.EmployeeImage.MediaType,
                        Option = "photo",
                        BusinessId = model.EmployeeId.ToString()
                    };
                    await _attachmentDAL.CreateAsync(attachmentEntity);
                }
                else
                {
                    if (attachmentEntity.AttachmentId != model.EmployeeImage.AttachmentId)
                    {
                        await _attachmentDAL.DeleteAsync(attachmentEntity);
                        attachmentEntity = new Attachment()
                        {
                            AttachmentId = model.EmployeeImage.AttachmentId,
                            FileName = model.EmployeeImage.FileName,
                            FileStream = model.EmployeeImage.FileStream,
                            Extension = model.EmployeeImage.Extension,
                            MediaType = model.EmployeeImage.MediaType,
                            Option = "photo",
                            BusinessId = model.EmployeeId.ToString()
                        };
                        await _attachmentDAL.CreateAsync(attachmentEntity);
                    }
                }
            }

            entity.EmployeeStatus = model.EmployeeStatus;
            await _employeeDAL.UpateAsync(entity);
            await _employeeDAL.SaveChangesAsync();
        }

        public async Task DeleteAsync(Guid id)
        {
            var entity = await _employeeDAL.GetAsync(id);
            await _employeeDAL.DeleteAsync(entity);
            await _attachmentDAL.DeleteAsync(id.ToString());
            await _employeeDAL.SaveChangesAsync();
        }

        public async Task<IEnumerable<MainEmployeeModel>> Main(string deptid, DateTime? date)
        {
            var model1 = new MainEmployeeModel() { Category = "劳务人员", Today = await _employeeDAL.CountAsync(deptid, "劳务人员", date), Total = await _employeeDAL.CountAsync(deptid, "劳务人员", null), Working = await _employeeDAL.Count2Async(deptid, "劳务人员") };
            var model2 = new MainEmployeeModel() { Category = "管理人员", Today = await _employeeDAL.CountAsync(deptid, "管理人员", date), Total = await _employeeDAL.CountAsync(deptid, "管理人员", null), Working = await _employeeDAL.Count2Async(deptid, "管理人员") };
            var model3 = new MainEmployeeModel() { Category = "所有", Today = await _employeeDAL.CountAsync(deptid, null, date), Total = await _employeeDAL.CountAsync(deptid, null, null), Working = await _employeeDAL.Count2Async(deptid, null) };
            return new List<MainEmployeeModel>() { model1, model2, model3 };
        }

        public async Task<bool> Exists(string deptid, string identityNumber)
        {
            return await _employeeDAL.Exists(deptid, identityNumber);
        }
    }
}
